/**
 * 
 */
package org.tangram.component.xml;

import java.net.URL;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.convert.Registry;
import org.simpleframework.xml.convert.RegistryStrategy;
import org.simpleframework.xml.core.Persister;
import org.simpleframework.xml.strategy.Strategy;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @author han_feng
 * 
 */
public class DefintionManager {

	private static final Logger logger = LoggerFactory
			.getLogger(DefintionManager.class);

	private Serializer serializer;

	private Map<String, ComponentDefintion> componentDefintions = new ConcurrentHashMap<String, ComponentDefintion>();

	public DefintionManager() throws Exception {
		Registry registry = new Registry();
		Strategy strategy = new RegistryStrategy(registry);
		serializer = new Persister(strategy);

		registry.bind(ExtensionDefintion.class,
				ExtensionDefintionConverter.class);
	}

	/**
	 * 从XML文件加载构件定义
	 * 
	 * @param is
	 * @throws Exception
	 */
	public ComponentDefintion loadFromXML(URL url) throws Exception {

		if (url == null)
			throw new IllegalArgumentException("url is null");

		ComponentDefintion component = serializer.read(
				ComponentDefintion.class, url.openStream());

		component.setDescriptorURL(url);

		String key = component.getKey();
		// 重复加载检测
		if (componentDefintions.containsKey(key)) {

			component = componentDefintions.get(key);

			String url1 = url.getPath();
			URL temp = component.getDescriptorURL();
			String url2 = "";
			if (temp != null)
				url2 = temp.getPath();

			if (url1.equals(url2)) {
				return component;
			}
			// 重复构件描述，给出警告
			component = null;

			logger.warn(
					"检测到重复的构件描述文件\"{}\"，与已加载的描述文件\"{}\"描述了同一个构件\"{}\"，请检查构件描述！",
					new String[] { url1, url2, key });

		} else {
			componentDefintions.put(component.getKey(), component);
		}

		return component;
	}

	/**
	 * 获取已加载的构件定义
	 * 
	 * @return
	 */
	public Map<String, ComponentDefintion> getComponentDefintions() {
		return componentDefintions;
	}

}
